02. 웹 최적화

📝 Contents

웹 최적화란

  • 최고의 성능을 만드는 최적화 조건을 갖추는 것
  • 웹 최적화에는 크게 세 가지 방법이 있음

프런트엔드 최적화

  • 웹 UI/UX와 관련된 최적화
  • 주로 프런트엔드 성능과 관련 있는 HTML, 자바스크립트, CSS, 이미지 파일, 타사 파일 자체나 혹은 이들이 어우러져 콘텐츠를 만들어 낼 때 최적화를 진행
  • 웹의 성능은 프런트엔드에 좌우됨
  • 프런트엔드 최적화 기술은 웹 브라우저를 실제로 사용하는 사용자 환경에 따라 달라짐
  • 프런트엔드를 최적화하는 대표적 기술은 아래와 같음
    • 스크립트를 병합하여 브라우저의 호출 개수를 줄임
    • 스크립트 크기를 최소화해 바이트(byte) 자체를 줄임
    • 스크립트를 gzip 등으로 압축하여 전달
    • WebP 등으로 브라우저 이미지 형식을 최적화
    • 이미지 손실, 무손실 압축
    • Cache-Control 응답 헤더를 통해 브라우저 캐시를 충실히 사용
    • 도메인 수를 줄여 DNS 조회를 최소화
    • DNS 정보 미리 읽어 오기
    • CSS를 HTML 상단에, 자바스크립트를 HTML의 하단에 위치시키기
    • 페이지 미리 읽어 오기(page prefetching)
    • 타사 스크립트가 웹 성능을 방해하지 않도록 조정

백엔드 최적화

  • 웹 UI를 로직에 맞게 만드는 백엔드 관련 최적화
  • 웹 서버, 웹 애플리케이션 서버, 데이터베이스, 로드 밸런싱, DNS 서버 등이 대표적인 백엔드
  • 이 시스템들을 튜닝해 정상 출력을 만드는 것이 백엔드를 최적화하는 목표
  • 다음은 대표적인 백엔드 최적화 방법
    • DNS 응답이 빨라지도록 서버 증설
    • DNS 응답을 빠르게 할 수 있도록 DNS 정보를 최대한 캐싱
    • 웹 서버가 있는 데이터 센터의 네트워크 출력/대역폭 증설
    • 웹 서버, 웹 애플리케이션 서버의 CPU/RAM 증설
    • 프록시 서버를 설정하여 웹 콘텐츠를 캐싱
    • CDN(Content Delivery Network)을 사용해 인터넷상에 콘텐츠 캐싱
    • 데이터베이스 정규화로 디스크 I/O 최적화
    • 데이터베이스 캐싱으로 응답을 빠르게
    • 로드 밸런싱을 통해 가장 성능이 좋은 웹 서버로 요청을 연결
    • 웹 애플리케이션 로직을 가볍고 빠르게 개발
  • 백엔드 최적화는 프런트엔드 최적화에 비해 가시적인 효과가 크지 않지만,
  • 웹 사이트의 빠른 로딩보다 네트워크를 정상적으로 사용하고 콘텐츠를 전달하기 위해 반드시 필요한 요소

프로토콜 최적화

  • 웹 콘텐츠를 전달하는 HTTP/HTTPS 프로토콜 자체의 효과를 극대화하면 웹 서버가 클라이언트에게 콘텐츠를 최대 속도와 최저 지연 시간으로 전달할 수 있음
  • 프로토콜 최적화는 웹 콘텐츠를 더 빠르게 요청하고 응답하도록 프로토콜을 업그레이드하는 과정

TCP/IP 프로토콜

  • 웹에서는 TCP/IP 프로토콜의 일종인 HTTP를 사용해 콘텐츠를 전달함
  • OSI 7개 계층 모델에서 TCP는 4번째인 전송 계층, HTTP는 7번째인 응용 계층에 속함
  • 전송 계층은 네트워크상에서 송신자와 수신자 사이에 데이터 전송을 보장하는 역할
  • 응용 계층은 실제 네트워크상에서 소프트웨어와 사용자의 상호 연동을 담당
  • 이 두개의 계층은 독립적인 것이 아니라 상위 계층인 응용 계층이 하위 계층인 전송 계층을 바탕으로 운용되는 구조임


  • TCP 네트워크를 사용하는 네트워크에 있어 대표적인 성능 지표는 대역폭과 지연 시간
  • 대역폭은 특정 시간 동안 얼마나 많은 네트워크 트래픽을 보낼 수 있는지 시간당 전송량을 의미
  • 지연 시간은 클라이언트와 서버 간 콘텐츠를 전달하는 물리적인 시간
    • 일반적으로는 클라이언트와 서버 사이 요청, 전달, 응답까지 걸리는 시간
    • 브라우저가 콘텐츠를 해석하고 화면에 렌더링하는 단계는 클라이언트 측에서만 실행하므로 지연 시간에는 포함되지 않음
  • 서버와 클라이언트 두 호스트를 모두 왕복하는 데 걸리는 지연 시간은 Round Trip Time(RTT)이라고 함
    • 이 값은 인터넷상에서 게임을 즐기거나 화상 채팅 등을 할 때 품질에 영향을 많이 주기 때문에,
    • 스트리밍 서비스 관련 회사들은 가변 스트리밍 방식을 사용
    • 가변 스트리밍 방식: 지연 시간이 길고 짧음에 따라 전달받는 영상 파일의 품질을 조절하여 버퍼링을 줄임
  • TCP와 웹 성능은 밀접한 관련이 있기 떄문에 TCP의 성능이 나빠지면 웹 성능도 영향을 받음
  • 성능 저하 요소를 해결하는 TCP 기술들이 있음

TCP 혼잡 제어

  • TCP 네트워크의 통신량을 조절하여 TCP 네트워크가 혼잡해지지 않도록 하는 방식
  • TCP 네트워크의 통신량이 실제 처리량보다 많아서 문제가 발생하는 것을 TCP 혼잡 붕괴라고 함
  • TCP 혼잡 붕괴는 인터넷에 연결된 호스트들이 최대한 많은 정보를 전송하려고 많은 네트워크 패킷을 보내기 때문에 발생함
  • 패킷을 보내는 쪽에서 네트워크에서 수용할 수 있는 양을 파악하고 그만큼의 패킷만 보내는 약속으로 TCP 혼잡 해결
  • 받는 쪽은 패킷이 정상적으로 송신되었음을 알리는 ACK 패킷을 보내며 ACK 패킷을 받은 호스트는 지속적으로 패킷을 보낼 수 있음
  • 호스트가 네트워크 상태를 시시각각 파악하고 전송 속도를 조절하는 것 또한 혼잡 제어 기능 중 하나
  • 혼잡 제어의 대표 기술들은 다음과 같음
느린 시작
  • TCP 연결이 시작되면 전송 가능한 버퍼의 양인 혼잡 윈도우의 초깃값을 작게 설정하여 전송
  • 통신이 시작되면 먼저 패킷을 1개만 보내고 ACK를 받으면 처음의 2배인 2개를 보냄
  • 패킷이 정상적으로 도착할 때마다 더 많은 패킷을 보내고, 이를 패킷 유실이 발생하기 전까지 반복하는 방식
  • 호스트가 ACK 응답을 받지 못하면 혼잡 윈도우의 크기는 더 이상 늘어나지 않음
  • 이 기술은 HTTP에서도 그대로 사용되며 웹 사이트에 접속한 브라우저는 처음부터 많은 패킷을 보내지 않음
빠른 재전송
  • 먼저 도착해야 하는 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 수신자가 일단 ACK 패킷을 보내는 방식
  • 중간에 패킷이 하나 손실되면 송신자는 중복된 ACK 패킷을 통해 이를 감지하고 정상적으로 전송되지 않은 패킷을 재전송
  • 중복된 패킷 3개 받으면 반드시 손실된 패킷을 재전송
  • 동시에 혼잡 제어가 필요한 상황임을 인식해 혼잡 윈도우 창 크기를 줄이는 작업도 실행
흐름 제어
  • TCP 송신자가 데이터를 너무 빠르게 혹은 너무 많이 전송하여 수신자의 버퍼가 오버플로(overflow)되는 현상을 방지하는 기술
  • 수신자는 수신 버퍼를 가지고 있는데 이로 인해 상위 계층으로 세그먼트를 보내는 애플리케이션 프로세스에서 데이터를 읽는 속도가 느려질 수 있음
  • 따라서 송신자가 데이터를 전송하는 속도를 애플리케이션 프로세스를 읽는 속도와 유사한 수준으로 만들어 트래픽 수신 속도를 송신 속도와 일치시키는 기술

HTTP 프로토콜

  • 웹은 HTTP 프로토콜을 통해 전달되므로 HTTP 성능을 개선하면 웹 성능도 향상됨

HTTP 최적화 기술

  • 웹 환경이 멀티호스트 환경으로 변하면서 HTTP/1.1 버전부터 멀티호스트 기능과 클라이언트와 서버 사이에서 TCP/IP 연결을 재사용하는 기능을 추가
  • HTTP/1.1 버전부터 적용된 연결 재사용, 파이프라이닝 기법이 바로 연결 기반의 HTTP 최적화 기술

HTTP 지속적 연결

  • TCP의 통신을 연결하는 3-way handshake 방식은 클라이언트와 서버 사이 SYN, SYN-ACK, ACK의 3번의 요청과 응답으로 이루어짐
  • HTTP 초기 버전에서는 3-way handshake 방식으로 TCP 연결을 맺었는데, 동시에 많은 웹 콘텐츠를 전달해야 하는 HTTP 통신에서 번거로움이 발생함
  • 두 개의 HTTP 요청과 응답을 위해 위 그림처럼 매번 TCP 연결을 맺고 끊는 알고리즘을 사용한다면 결국 웹 로딩 시간에도 영향을 줌
  • 초기 웹 페이지는 콘텐츠의 개수가 많지 않았기에 매번 TCP 연결을 사용해도 큰 불편이 없었지만 콘텐츠 수가 점점 다양해지면서 웹 성능에 걸림돌이 됨
  • TCP 연결 재사용이 필요하게 되어 등장한 것이 지속적 연결 기술
  • 지속적 연결은 keep-alive 혹은 연결 재사용이라는 용어로도 불림
  • HTTP 지속적 연결은 클라이언트와 서버가 TCP상에서 한 번 연결되면 둘 사이의 연결이 완전하게 끊어지기 전까지 맺어진 연결을 지속적으로 재사용 하는 기술
  • HTTP/1.0에서는 지속적 연결 사용을 위해 클라이언트가 지속적 연결을 지원하는 웹 서버에 요청 헤더를 이용하여 Connection 헤더 및 keep-alive 속성으로 요청해야함
    • Connection: keep-alive
  • 지속적 연결을 지원하는 웹 서버는 클라이언트의 요청을 수용하여 HTTP 응답 후 동일한 헤더를 HTTP 응답에 포함하는 것이 HTTP/1.0 RFC 규약이 됨
  • HTTP/1.1 버전에서는 Connection 헤더를 사용하지 않아도 모든 요청과 응답이 HTTP 지속적 연결을 기본으로 지원함
  • 필요 없는 경우에만 close 요청을 통해 지속적 연결을 사용하지 않겠다고 전달
    • Connection: close
  • 서버에 연결된 모든 클라이언트의 TCP 연결이 계속 늘어나면 자원이 고갈되어 더 많은 클라이언트가 접속할 때 대처하지 못하는 상황이 발생할 수 있음
  • 반대로 HTTP 지속적 연결을 사용함으로써 단일 시간 동안 TCP 연결의 수를 줄여 서버의 CPU나 메모리 자원을 절약하고 네트워크 혼잡이나 지연을 줄이는 장점도 있음
  • 멀티플렉싱 기술의 토대로 만들어진 HTTP/2를 사용한다면 더 이상 지속적 연결을 고민할 필요가 없는데, 이는 이후에 자세히 다룰 예정

HTTP 파이프라이닝

  • 먼저 보낸 요청의 응답이 없어도 다음 요청을 병렬적으로 수신자 측에 전송하는 기술
  • 중간에 응답 지연이 발생하더라도 클라이언트는 먼저 서버 측의 응답을 받을 수 있어 전체적으로 빠른 웹 로딩이 구현되는 구조
  • HTTP 파이프라이닝 기술을 사용하려면 HTTP 지속적 연결 기능이 꼭 지원되어야 함

DNS

  • 인터넷 호스트명을 클라이언트와 서버가 이해할 수 있는 IP 주소로 변환해주는 시스템
  • DNS 질의와 응답 성능이 나쁘면 웹 사이트 로딩에 영향을 줄 수 있음

DNS의 작동 원리

  1. 로컬 DNS 서버로 질의
    • 소유하지 않은 도메인 정보에 대한 질의를 받으면 전체 도메인을 관장하는 루트 DNS에 www.example.com 도메인에 대한 질의
  2. 루트 DNS 서버로 질의
    • www.example.com에 대한 정보가 없는 루트 DNS 서버는 .com 도메인 서버의 IP 정보를 알려줌
  3. .com DNS 서버로 질의
    • www.example.com에 대한 정보가 없는 루트 DNS 서버는 example.com 네임 서버의 IP 정보를 알려줌
  4. example.com DNS 서버로 질의

    • 자신이 알고 있는 www.example.com 네임 서버의 IP 정보를 알려줌
  5. 도메인을 IP 주소로 질의하여 질의하여 값을 받아오는 과정에는 하나의 DNS 서버가 아니라 도메인 구조 계층에 따라 각각의 DNS 서버들이 관여: 반복적 질의

  6. 로컬 DNS 서버들은 사용자가 이용중인 ISP 업체나 DNS 전문 서비스 업체 등이 관리
  7. 루트 DNS 서버는 ICANN 기관에서 관리

사용 중인 다양한 도메인 확인 방법

  • 최근 웹 사이트는 자신의 웹 서비스 콘텐츠뿐만 아니라 다른 웹 서비스의 다양한 콘텐츠를 호출하여 사용
  • 크롬 브라우저의 개발자도구에서 Source 항목을 통해 하나의 웹 페이지에서 어떤 도메인들이 사용되고 있는지 쉽게 파악 가능
  • 다양한 서비스들이 각 공급자 도메인을 사용하기 때문에, 자신의 운영중인 웹 서비스 도메인 성능이 빠르다고 해서 DNS를 조회할 때 웹 성능에 문제가 없다고 판단하기 어려움

웹 성능을 최적화하는 도메인 운용 방법

  • 직접 개발한 서비스에 도메인 분할을 하고 싶다면 상위 도메인을 동일하게 해 DNS 질의를 최대한 적게 만드는 것을 권장
  • 공통된 상위 도메인을 사용하는 서비스들은 도메인 질의를 담당하는 네임 서버에 캐싱된 정보를 재사용 할 수 있어 DNS 질의 시간을 단축시킴
  • 동일한 상위 도메인을 사용하면 HTTPS 사용을 위한 SSL 인증서를 와일드카드 형식으로 하나만 생성해도 모든 도메인에 사용할 수 있어, 인증서 발급 비용과 수고를 줄일 수 있음


  • HTML의 DNS 프리페치 기능을 사용하면 웹 페이지에 사용된 도메인들의 DNS를 조회하는 시간이 좀 더 빨라짐
  • DNS 프리페치란 하나의 웹 페이지에 다수의 도메인 호스트명이 섞여 있을 때 웹 문서 페이지를 여는 시점에 멀티스레드 방식으로 미리 DNS를 조회해 빠르게 IP 주소를 불러오는 기술
  • <link> 태그의 지시자 구문에 'dns-prefetch'라는 명령어를 사용해 페이지 상단에서 미리 DNS를 조회하면 브라우저는 웹 콘텐츠를 다운로드함과 동시에 DNS를 조회하여 성능이 더 빨라짐
    • <link rel="dns-prefetch" href="//img.feokorea.com">

브라우저

  • HTTP, DNS를 사용해 사용자가 원하는 HTML, 이미지, 오디오, 동영상 등의 웹 콘텐츠를 전달하는 소프트웨어
  • HTTP가 빠르게 웹 콘텐츠를 전달해도 이를 사용자에게 제공하는 브라우저가 빠르게 작동하지 않으면 전반적인 웹 성능은 느림
  • 웹 성능을 최종 테스트하거나 디버깅하는 작업은 대체로 브라우저를 통해 수행
  • 다음은 브라우저를 이용해 웹 사이트의 성능을 확인하는 방법

내비게이션 타이밍 API

  • 네비게이션 타이밍 API는 웹 사이트의 성능을 측정하는 데 사용할 수 있는 데이터를 제공
  • 이전까지는 브라우저의 자바스크립트 기능을 이용해 웹 페이지가 열리는 시간과 로딩이 완료되는 시간 차이를 계산함으로써 웹 로딩 시간을 구할 수 있었음
  • 네비게이션 타이밍 API는 더 유용하고 정확한 종단간 대기 시간 정보를 제공
  • API는 window.performance 개체(object)의 속성(property)으로 사용할 수 있음

네비게이션 타이밍 속성

  • 개발자 도구의 콘솔에 performance를 입력하고 timing을 확인하면 API에서 정의한 웹 브라우저가 웹 페이지를 로딩 시 실행하는 각 단계의 완료된 시간을 Unix Epoch Time 형식으로 변환된 값으로 볼 수 있음
  • 네비게이션 타이밍 속성들이 각각 어떤 것을 의미하는지는 책 2.5.3절의 표 2-1 참고

네비게이션 타이밍 속성값 구하기

  • 네비게이션 타이밍 속성값 구하는 자세한 예제는 책 2.5.4절을 보면 알 수 있음

💭 Insights

빠른 재전송의 중복 ACK

  • 빠른 재전송에서 먼저 도착해야 하는 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 수신자가 일단 ACK 패킷을 보낸다고 하는데 이때 어떤 ACK을 보내서 손실을 알 수 있는지 궁금하다.
  • 중간에 패킷이 하나 손실되면 송신자는 중복된 ACK 패킷을 통해 이를 감지하고 정상적으로 전송되지 않은 패킷을 재전송한다고한다.
  • 이 때 중복된 ACK이 어떤 형태로 가서 이를 감지할 수 있나 찾아 보았다.


  • 빠른 재전송의 예시를 찾아보았다.
  • 1-6번의 패킷이 순서대로 와야 하는 상황을 예시로 들면,
  • 1번 패킷이 도착하면 응답으로 ACK1, 2번 패킷이 도착하면 응답으로 ACK2를 보낸다.
  • 3번 패킷이 손실된다면 2번 다음에 4-6번 패킷이 도착한다.
  • 이때 4-6번 패킷을 받으면 응답으로 중복 ACK인 ACK2를 보낸다.
  • 중복된 패킷 3개 받으면 반드시 손실된 패킷을 재전송이라고 책에 나온다.
  • 따라서 4-6번 패킷이 도착해 중복 ACK인 ACK2를 3번 보내게 되면 송신자는 손실된 3번 패킷을 즉시 전송하는 것이다.

지속적 연결의 자원고갈

  • 지속적 연결을 하면 서버에 연결된 모든 클라이언트의 TCP 연결이 계속 늘어나면 자원이 고갈되어 더 많은 클라이언트가 접속할 때 대처하지 못하는 상황이 발생할 수 있다고 나온다.
  • 또 반대로 HTTP 지속적 연결을 사용함으로써 단일 시간 동안 TCP 연결의 수를 줄여 서버의 CPU나 메모리 자원을 절약하고 네트워크 혼잡이나 지연을 줄이는 장점도 있다고 나온다.
  • 그럼 지속적 연결을 사용하면 서버 자원이 고갈되는 것인건가 절약되는 것인가?


  • 지속적 연결로 모든 클라이언트와 서버 간 TCP 연결을 계속 유지하면, 오랜 시간 동안 사용되지 않거나 불필요하게 연결을 유지할 경우, 서버의 연결 수가 계속 증가해 자원이 고갈될 위험이 있다. 특히 동시에 많은 클라이언트가 연결을 유지하는 환경에서는 서버 자원이 부족해질 수 있다.
  • 지속적 연결은 일정 조건이나 설정에 따라 끊어진다.
  • 반면, 지속적 연결을 통해 요청마다 새로운 TCP 연결을 설정하지 않아도 되기 때문에 단일 시간 동안 TCP 연결 수가 줄어들고, 각 요청마다 발생하는 오버헤드가 감소하게 된다. 결과적으로 서버의 CPU와 메모리 사용량이 절약되며, 연결 설정과 해제에 필요한 자원을 줄임으로써 네트워크 혼잡과 지연을 완화할 수 있다.
  • 결과적으로 지속적 연결을 사용하면 단일 시간 동안 TCP 연결 수가 줄어들어 그에 해당하는 오버헤드가 감소하게 되지만, 연결을 끊지 않고 계속 유지하게 된다면, 서버에 연결을 유지할 수 있는 connection pool이 줄어들어 자원이 고갈 될 수 있는 것이다.
  • 서버에 연결될 수 있는 클라이언트는 한정되어 있다. 모든 클라이언트를 다 연결된 채로 유지한다면 사용자가 많은 서비스에는 큰 부하가 걸릴 수 있다.
  • 따라서 지속적 연결을 적절하게 사용해야 서버 자원을 잘 관리 할 수 있다.

results matching ""

    No results matching ""